﻿#region LGPL License

/*
OpenSearchNet
Copyright (c) 2014, Brad Hards <bradh@frogmouth.net>, All rights reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library.
*/

#endregion LGPL License

using System;

namespace OpenSearch
{
    /// <summary>
    /// Subclass XmlTextReader that is tolerant of date formats
    /// </summary>
    /// <remarks>
    /// <para>
    /// See http://support.microsoft.com/kb/2020488 for details
    /// </para>
    /// </remarks>
    internal class DateFixerXmlTextReader : System.Xml.XmlTextReader
    {
        private bool readingDate = false;
        private bool readingEmptyDate = false;
        private const string CustomUtcDateTimeFormat = "ddd MMM dd HH:mm:ss Z yyyy"; // Wed Oct 07 08:00:07 GMT 2009

        public DateFixerXmlTextReader(System.IO.Stream s)
            : base(s)
        {
        }

        public DateFixerXmlTextReader(System.IO.StringReader sr)
            : base(sr)
        {
        }

        public override void ReadStartElement()
        {
            if ((base.NamespaceURI == Constants.NSAtom) && (string.Equals(base.LocalName, "updated")) && (base.IsEmptyElement))
            {
                readingEmptyDate = true;
            }
            else
            {
                if (string.IsNullOrEmpty(base.NamespaceURI) &&
                       ((string.Equals(base.LocalName, "lastBuildDate", StringComparison.OrdinalIgnoreCase)) ||
                        (string.Equals(base.LocalName, "pubDate", StringComparison.OrdinalIgnoreCase))))
                {
                    readingDate = true;
                }
                base.ReadStartElement();
            }
        }

        public override void ReadEndElement()
        {
            if (readingEmptyDate)
            {
                readingEmptyDate = false;
                base.Read();
            }
            else
            {
                if (readingDate)
                {
                    readingDate = false;
                }
                base.ReadEndElement();
            }
        }

        public override string ReadString()
        {
            if (readingEmptyDate)
            {
                DateTime dt = new DateTime(); // Invalid
                string dtAsString = OpenSearch.Convert.DateTimeToString(dt);
                return dtAsString;
            }
            else if (readingDate)
            {
                string dateString = base.ReadString();
                DateTime dt;
                if (!DateTime.TryParse(dateString, out dt))
                    dt = DateTime.ParseExact(dateString, CustomUtcDateTimeFormat, System.Globalization.CultureInfo.InvariantCulture);
                return dt.ToUniversalTime().ToString("R", System.Globalization.CultureInfo.InvariantCulture);
            }
            else
            {
                return base.ReadString();
            }
        }
    }
}